﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace MailSlot
{
    /// <summary>
    /// Wrapper class to create an endpoint for Mailslot messages. By default creates the connection
    /// to mailslots on the local machine.
    /// </summary>
    public class MailslotClient : IDisposable
    {
        private Mailslot.SafeMailslotHandle _handle;
        private readonly string _name;
        private readonly string _machine;

        /// <summary>
        /// Create a new Mailslot endpoint for sending messages. The mailslot is created on the local machine.
        /// </summary>
        /// <param name="name">Name of the mailslot to which messages should be sent.</param>
        public MailslotClient(string name) : this(name, ".") { }

        /// <summary>
        /// Create a new Mailslot endpoint for sending messages. The mailslot is created on the given machine name. Use "." for
        /// the local machine.
        /// </summary>
        /// <param name="name">Name of the mailslot to which messages should be sent.</param>
        /// <param name="machine">Name of the machine where the messages should be sent.</param>
        public MailslotClient(string name, string machine)
        {
            _name = name;
            _machine = machine;
        }

        /// <summary>
        /// Sends a given text message to the previously configured machine/mailslot.
        /// </summary>
        /// <param name="msg">Message to send.</param>
        public void SendMessage(string msg)
        {
            if (_handle == null) CreateHandle();

            int bytesWritten;

            byte[] bMessage = Encoding.Unicode.GetBytes(msg);

            bool succeeded = Mailslot.WriteFile(_handle, bMessage,
                 bMessage.Length, out bytesWritten, IntPtr.Zero);

            if (!succeeded || bMessage.Length != bytesWritten)
            {
                if (_handle != null) _handle.Close();
                _handle = null;

                throw new Win32Exception();
            }
        }

        public void Dispose()
        {
            if (_handle != null)
            {
                _handle.Close();
                _handle = null;
            }
        }

        private void CreateHandle()
        {
            _handle = Mailslot.CreateFile(
                @"\\" + _machine + @"\mailslot\" + _name,
                Mailslot.FileDesiredAccess.GenericWrite,
                Mailslot.FileShareMode.FileShareRead,
                IntPtr.Zero,
                Mailslot.FileCreationDisposition.OpenExisting,
                0,
                IntPtr.Zero);

            if (_handle.IsInvalid) throw new Win32Exception( Marshal.GetLastWin32Error() );

        }
    }
}
